package nina.yiyou.attendance.s30pattern.compute

import nina.yiyou.attendance.s10merge.compute.AttendDetailMerger
import nina.yiyou.attendance.s10merge.input.AttendLeaveExcelReader
import nina.yiyou.salary.output.util.KeyPrefixPrepender

import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
import java.util.stream.Collectors

import static java.util.stream.Collectors.groupingBy

class PatternEmployeeMerger {

  PatternEmployeeMerger(List<AttendDetailMerger.DayResult> dayList) {
    _dayList = dayList
  }

  List<Map> merge() {
    return _dayList.stream()
        .collect(groupingBy { AttendDetailMerger.DayResult d -> d.employeeId() })
        .values().stream()
        .flatMap() { expandEmployee(it).stream() }
        .collect(Collectors.toList())
  }

  private List<Map> expandEmployee(List<AttendDetailMerger.DayResult> days) {
    def am = ['上午', [9, 30], [12, 30]]
    def pm = ['下午', [14, 00], [18, 30]]

    def getDate = { AttendDetailMerger.DayResult d -> d.dayBasic().date() }
    Map dayMap = days.stream().collect(Collectors.toMap(getDate, { it }))

    return [
        makePartLine(dayMap, am),
        makePartLine(dayMap, pm),
    ]
  }

  private Map<String, Object> makePartLine(Map dayMap, List part) {
    AttendDetailMerger.DayResult day = dayMap.values().first()

    def makeTime = { List<Integer> cfg -> LocalTime.of(cfg[0], cfg[1]) }
    LocalTime start = makeTime(part[1] as List<Integer>)
    LocalTime end = makeTime(part[2] as List<Integer>)

    def getKey = { Map.Entry e -> e.getKey() }
    def getVal = { Map.Entry e -> resolveLeave(e.value as AttendDetailMerger.DayResult, start, end) }
    Map dateResult = dayMap.entrySet().stream().collect(Collectors.toMap(getKey, getVal))

    return day.toMap() + new KeyPrefixPrepender([
        '时间': part[0],
    ] + dateResult, '计算3').prepend()
  }

  private String resolveLeave(AttendDetailMerger.DayResult day, LocalTime start, LocalTime end) {
    LocalDate date = day.dayBasic().date()
    LocalDateTime startPoint = date.atTime(start)
    LocalDateTime endPoint = date.atTime(end)

    Set<String> leaveSet = day.dayBasic().leaveList().stream()
        .filter { isLeaving(it, startPoint, endPoint) }
        .map { it.leaveType() }
        .collect(Collectors.toSet())

    for (List<String> item : LEAVE) {
      String type = item[0]
//      println(day.dayBasic().info().name() + ' ' + type)
      if (leaveSet.contains(type)) {
        return item[1]
      }
    }

    return ''
  }

  private boolean isLeaving(AttendLeaveExcelReader.Line leaveLine, LocalDateTime start, LocalDateTime end) {
    assert leaveLine.isValid()
    if (end.isBefore(leaveLine.startTime())) {
      return false
    }
    if (start.isAfter(leaveLine.endTime())) {
      return false
    }
    return true
  }

  // 包含优先级
  private static final List LEAVE = [
      ['事假', '※'],
      ['调休假', '△'],
      ['年假', '∞'],
      ['病假', '◇'],
  ]

  private final List<AttendDetailMerger.DayResult> _dayList
}
